#pragma once 
#include<iostream>
#include<pthread.h>
#include<queue>
#include"task.hpp"
#define MAX_NUM 1
using namespace std;
class ThreadPool
{

  private:
    queue<Task> q;
    static pthread_mutex_t lock;
		pthread_mutex_t _lock;
    pthread_cond_t cond;
    static ThreadPool* ptr;
  private:
    ThreadPool()
    {
      Thread_init();
    }
		ThreadPool(const ThreadPool&)=delete;
    ThreadPool& operator=(const ThreadPool&)=delete;

  public:
    static ThreadPool* GetThreadPoolObj()
    {
      if(ptr==nullptr)
      {
        pthread_mutex_lock(&lock);
        if(ptr==nullptr)
        {
          ptr=new  ThreadPool();
        }
        pthread_mutex_unlock(&lock);
      }
      return ptr;
    }
		
		void Lock()
		{
			pthread_mutex_lock(&_lock);
		}

		void UnLock()
		{
			pthread_mutex_unlock(&_lock);
		}

    void threadwait(){
       pthread_cond_wait(&cond,&_lock);                   
    }
    void threadroude(){
      pthread_cond_signal(&cond);                  
    }
	  
    void Push(Task& t){
        Lock();
        q.push(t);
        UnLock();
        threadroude();
    }

    void Pop(Task& out){
        out=q.front();
        q.pop();
     }

    void Thread_init()
    {
       pthread_mutex_init(&_lock,nullptr);
       pthread_cond_init(&cond,nullptr);
       for(int i=0;i<	MAX_NUM;i++){
       		pthread_t pid;
         	if(pthread_create(&pid,nullptr,Thread_hander,this)!=0){
						LOG(ERROR,"PTHREAD_CREATE"); 
            break;                                                                                          
          }
          pthread_detach(pid);                                                                      
       }                                  
		}
    
    bool empty()
    {
      return q.empty();
    }

    //线程执行函数
    static void* Thread_hander(void* agr)
    {
      ThreadPool* tp=(ThreadPool*)agr;
        while(true){
          Task t;
          tp->Lock();
          if(tp->empty()){
              tp->threadwait();
          }
          tp->Pop(t);
          tp->UnLock();
          t.Hander();
      }
    }
    
    int Qsize()
    {
      return q.size();
    }
};
ThreadPool* ThreadPool::ptr=nullptr;
pthread_mutex_t  ThreadPool::lock=PTHREAD_MUTEX_INITIALIZER;
